package com.msg.utils;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.mina.core.future.WriteFuture;
import org.apache.mina.core.session.IoSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.pjc.annotation.CliToSrv;
import com.pjc.annotation.Protocol;
import com.pjc.annotation.SrvToSrv;
import com.pjc.utils.ClassUtils;
import com.pjc.utils.ConfigUtil;

/**
 * 消息服务器缓存类
 * 
 * @author 王畅
 * @since 2015年6月14日
 */
public class MsgSrvUtils {

	private static final Logger log = LoggerFactory.getLogger(MsgSrvUtils.class);

	public static int serverId = 1;
	private static MsgSrvUtils instance;
	private static ConcurrentHashMap<String, Map<String, IoSession>> sessionMap = new ConcurrentHashMap<String, Map<String, IoSession>>();
	private final ConcurrentHashMap<Integer, Method> methodMap = new ConcurrentHashMap<Integer, Method>();
	private final ConcurrentHashMap<Integer, Method> cliToSrv = new ConcurrentHashMap<Integer, Method>();

	private MsgSrvUtils() {
	}

	public static MsgSrvUtils getInstance() {
		synchronized (MsgSrvUtils.class) {
			if (instance == null)
				instance = new MsgSrvUtils();
		}
		return instance;
	}

	public void setUp() {

		String scanPackage = ConfigUtil.getInstance().getStringProperties("auto.scan.package");
		log.debug("开始扫描服务包：" + scanPackage);
		Set<Class<?>> classes = ClassUtils.getClasses(Thread.currentThread().getContextClassLoader(), scanPackage);
		scanProtocolServiceAanno(classes);
		scanCliToSrvAanno(classes);
	}

	private void scanProtocolServiceAanno(Set<Class<?>> classes) {
		if ((classes == null) || (classes.size() == 0)) {
			log.debug("扫描SrvToSrv类失败！");
			return;
		}
		for (Class<?> cla : classes) {
			Annotation anno = cla.getAnnotation(SrvToSrv.class);
			if (anno == null)
				continue;
			for (Method method : cla.getMethods()) {
				Annotation methodAnno = method.getAnnotation(Protocol.class);
				if (methodAnno == null)
					continue;
				Protocol protoAnno = (Protocol) methodAnno;
				int protoId = protoAnno.protoId();
				if (protoId == 0)
					continue;
				log.debug("protoId：" + protoId + ";Method：" + method.getName());
				this.methodMap.put(Integer.valueOf(protoId), method);
			}
		}
	}

	private void scanCliToSrvAanno(Set<Class<?>> classes) {
		if ((classes == null) || (classes.size() == 0)) {
			log.debug("扫描CliToSrv类失败！");
			return;
		}
		for (Class<?> cla : classes) {
			Annotation anno = cla.getAnnotation(CliToSrv.class);
			if (anno == null)
				continue;
			for (Method method : cla.getMethods()) {
				Annotation methodAnno = method.getAnnotation(Protocol.class);
				if (methodAnno == null)
					continue;
				Protocol protoAnno = (Protocol) methodAnno;
				int protoId = protoAnno.protoId();
				if (protoId == 0)
					continue;
				log.debug("protoId：" + protoId + ";Method：" + method.getName());
				this.cliToSrv.put(Integer.valueOf(protoId), method);
			}
		}
	}

	public Method getMethod(int protoId) {
		return (Method) this.methodMap.get(Integer.valueOf(protoId));
	}

	public Method getCliMsgHanderMethod(int protoId) {
		return (Method) this.cliToSrv.get(Integer.valueOf(protoId));
	}

	public static void addSession(IoSession session, String userId, String appID) {
		if (!sessionMap.containsKey(appID)) {
			Map<String, IoSession> appSessionMap = new HashMap<String, IoSession>();
			appSessionMap.put(userId, session);
			sessionMap.put(appID, appSessionMap);
		} else {
			sessionMap.get(appID).put(userId, session);
		}
	}

	public static IoSession delSession(String userId, String appID) throws Exception {
		if (!sessionMap.containsKey(appID)) {
			return null;
		}
		return sessionMap.get(appID).remove(userId);
	}

	public static boolean existSession(String userId, String appID) {
		if (!sessionMap.containsKey(appID)) {
			return false;
		}
		return sessionMap.get(appID).containsKey(userId);
	}

	public static IoSession getSession(String userId, String appID) {
		if (!sessionMap.containsKey(appID))
			return null;
		return sessionMap.get(appID).get(userId);
	}

	public static int getSessionSize(String appID) {
		return sessionMap.get(appID).size();
	}

	public static Iterator<Map.Entry<String, Map<String, IoSession>>> getSessions() {
		return sessionMap.entrySet().iterator();
	}

	public static void broadcastMsg(Object msg, String appID) {
		Iterator<Map.Entry<String, IoSession>> it = sessionMap.get(appID).entrySet().iterator();
		while (it.hasNext())
			write(it.next().getValue(), msg);
	}

	public static boolean write(IoSession seesion, Object obj) {
		if (seesion == null || seesion.isClosing() || !seesion.isConnected())
			return false;
		WriteFuture future = seesion.write(obj);
		future.awaitUninterruptibly();
		log.info("发送消息：>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>:" + obj.toString());
		return future.isDone();

	}

}
